iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0

前言

今天的內容會接續昨天,所以如果還沒看過前一篇的可以先去看一下[Day24]不可不知的小工具-string.Length。昨天有提到我要匯入資料的時候,在程式面端就已經丟出exception了。今天的前提假設是程式碼端已經通過檢核,要進入寫入資料庫端的階段了。
註: 使用的是T-SQL

一樣先來認識下面幾個東西

NVARCHAR(n)

先來看看微軟文件的說明

可變大小字串資料。 n 會定義字串大小 (以位元組配對為單位),可以是 1 到 4,000 的值。 max 表示儲存體大小上限是 2^31-1 個字元 (2 GB)。 儲存大小是 n 位元組的兩倍 + 2 位元組。 針對 UCS-2 編碼,儲存大小是 n 位元組的兩倍 + 2 位元組,而可存放的字元數目也是 n。 針對 UTF-16 編碼,儲存大小仍是 n 個位元組的兩倍 + 2 個位元組,但可儲存的字元數目可能小於 n

謎之音:你最好是看得懂微軟文件在說什麼????
簡單來說,nvarchar(max)可以儲存大約21億多個字元,也就是說nvarchar(max)大約可以存21億多個字母/標點符號...等。如果套用到昨天的情境來說,nvarchar(500)可以儲存的大小就是1002個位元組,但可能會少於500個字元。順帶一提,SQL Server預設的編碼方式為UTF-16

如果關於nvarchar的內容有大致了解,就讓我們繼續看下去!

LEN()

再來看看微軟文件又說了什麼

傳回指定字串運算式的字元數,但尾端空格不算。

可以講人話嗎....???
意思就是說如果使用LEN()這個函式,會回傳這個字串的字母/符號/空白的數量,但是最後面的空格並不會被算進去。

DATALENGTH()

還是要再來看看微軟文件說了什麼

此函式會傳回用來代表任何運算式的位元組數目。

意思是說DATALENGTH()這個函式回傳的內容是位元數目,而不是字元數目。下面舉例讓大家瞭解一下

舉例

說明: 宣告一個變數,欄位大小開nvarchar(40)。變數內容裡面有6個中文字和2個空白(一個在中間一個在尾端)
用SSMS執行語法實際結果會是
LEN() => 7個字元,6個中文字加上中間一個空白
DATALENGTH() => 16個位元組, (6個中文字)*2位元組 + (2個空白) *2位元組
https://ithelp.ithome.com.tw/upload/images/20231009/20162714g65iVmPuVB.jpg

講了這麼多,跟昨天的關聯又在哪裡了???讓我們繼續看下去

回歸正題

先附上我要存進資料庫的內容,已知這段越南文有627個字元,DATALENGTH()結果為1254。資料庫存放該內容的欄位大小是nvarchar(500)
https://ithelp.ithome.com.tw/upload/images/20231009/20162714FMXVpvrMHq.jpg

根據上面的內容,可以知道nvarchar(500)可以存的位元組大小為1002。所以真的要存進資料庫的話,這段內容也是會被截斷。不會完整的被存進資料庫內!

結論

沒有這次的踩雷經驗,真的是不會特別去搜尋這些資訊。找資料過程中還有看到UTF-16、UTF-8...編碼的形式也都會影響。希望這個分享可以幫助到大家~

參考

nchar 和 nvarchar (Transact-SQL)
LEN (Transact-SQL)
DATALENGTH (Transact-SQL)

文章同步發布於:個人部落格


上一篇
[Day24]不可不知的小工具-string.Length
下一篇
[Day26]不可不知的小工具-C#字串長度處理
系列文
懶還要更懶,快還要更快。不可不知的小工具和知識30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言